昨日我們使用WebSocket
技術建立了一個簡單聊天室,不過每次重新刷新畫面後聊天室的記錄就消失了,
讓我們使用 sqflite
來處理聊天室的訊息記錄吧。
sqflite
是一個用來操作 SQLite 資料庫的套件,我們在 pubspec.yaml
加入套件設定
dependencies:
flutter:
sdk: flutter
web_socket_channel: ^2.1.0
rxdart: ^0.27.2
sqflite: ^2.0.0+4
path: ^1.8.0
首先我們使用 dart singleton 語法產生一個操作 db 的實例
class ChatDB {
static final ChatDB _instance = ChatDB._internal();
Database? _db;
ChatDB._internal();
factory ChatDB() {
return _instance;
}
}
我們透過openDatabase
函式開啟資料庫,並通過onCreate
建立資料表
Future<Database> _initDB() async {
final dbPath = await getDatabasesPath();
return _db ??= await openDatabase(
join(dbPath, 'chat.sqlite'),
onCreate: (db, version) {
return db.execute(
'CREATE TABLE chat(id INTEGER PRIMARY KEY, by TEXT, msg TEXT, mid TEXT, time INTEGER)',
);
},
version: 1,
);
}
我們使用已定義好的 Message Model 類別,使用 insert
語法匯入資料
Future insert(Message msg) async {
final db = await _initDB();
await db.insert(
'chat',
msg.toJson(),
conflictAlgorithm: ConflictAlgorithm.replace,
);
}
也可以使用 sqlite SELECT 語法取得資料
Future<List<Message>> query() async {
final db = await _initDB();
final List<Map<String, dynamic>> maps =
await db.rawQuery('SELECT * FROM chat ORDER BY time DESC LIMIT 30;');
var data = List.generate(maps.length, (i) {
return Message.fromJson(maps[i]);
});
return List.from(data.reversed);
}
使用 sqlite DELETE 語法刪除特定資料
Future<int> delete(String mid) async {
final db = await _initDB();
return await db.rawDelete('DELETE FROM chat WHERE mid = ?', [mid]);
}
若確認不在使用需透過 close
關閉資料庫
Future<void> close() async {
final db = await _initDB();
await db.close();
}
在 StatefulWidget
生命週期 initState
階段從 DB 取回資料
@override
initState() {
super.initState();
chat.initData();
void initData() async {
data.addAll(await db.query());
stream.add(data);
}
delete(String mid) async {
await db.delete(mid);
data.removeWhere((item) => item.mid == mid);
stream.add(data);
}